/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.oai.repositoryManager.oaiId;

import cz.mzk.oai.repositoryManager.AbstractEntityManager;
import cz.mzk.oai.repositoryManager.EntityNotFoundException;
import cz.mzk.oai.repositoryManager.EntityPresentException;
import cz.mzk.oai.repositoryManager.IncorrectEntityException;
import javax.persistence.NoResultException;
import javax.persistence.Query;

/**
 *
 * @author Martin Rehanek (rehan@mzk.cz)
 */
public class OaiIdManagerImpl extends AbstractEntityManager implements OaiIdManager {

    private static final String QUERY_FIND_BY_BASE_SYSNO = "SELECT i FROM " + OaiIdentifierEntity.class.getSimpleName() + " i WHERE i.base = :base AND i.sysno = :sysno";

    public OaiIdentifierEntity findOaiId(String base, String sysno) throws EntityNotFoundException {
        checkParameters(base, sysno);
        Query query = getEntityManager().createQuery(QUERY_FIND_BY_BASE_SYSNO);
        query.setParameter("base", base);
        query.setParameter("sysno", sysno);
        try {
            OaiIdentifierEntity result = (OaiIdentifierEntity) query.getSingleResult();
            return result;
        } catch (NoResultException e) {
            throw new EntityNotFoundException(getEntityClassName(), getIdString(base, sysno));
        }
    }

    private boolean exists(String base, String sysno) {
        Query query = getEntityManager().createQuery(QUERY_FIND_BY_BASE_SYSNO);
        query.setParameter("base", base);
        query.setParameter("sysno", sysno);
        return !super.isEmpty(query);
    }

    public OaiIdentifierEntity createOaiId(String base, String sysno) throws EntityPresentException {
        checkParameters(base, sysno);
        if (exists(base, sysno)) {
            throw new EntityPresentException(getEntityClassName(), getIdString(base, sysno));
        }
        OaiIdentifierEntity oaiId = new OaiIdentifierEntity();
        oaiId.setBase(base);
        oaiId.setSysno(sysno);
        getEntityManager().getTransaction().begin();
        getEntityManager().persist(oaiId);
        getEntityManager().getTransaction().commit();
        return oaiId;
    }

    private void checkParameters(String base, String sysno) {
        if (base == null) {
            throw new NullPointerException("base");
        }
        if (sysno == null) {
            throw new NullPointerException("sysno");
        }
    }

    public void removeOaiId(OaiIdentifierEntity oaiId) throws IncorrectEntityException {
        if (!isManagedEntity(oaiId)) {
            throw new IncorrectEntityException(getEntityClassName(), getEntityIdString(oaiId));
        }
        getEntityManager().getTransaction().begin();
        try {
            getEntityManager().remove(oaiId);
        } catch (IllegalArgumentException e) {
            throw new IncorrectEntityException(getEntityClassName(), getEntityIdString(oaiId));
        } finally {
            getEntityManager().getTransaction().commit();
        }
    }

    protected String getEntityClassName() {
        return OaiIdentifierEntity.class.getCanonicalName();
    }

    @Override
    protected String getEntityIdString(Object entity) {
        if (!(entity instanceof OaiIdentifierEntity)) {
            throw new IllegalArgumentException("not instance of " + OaiIdentifierEntity.class.getCanonicalName());
        }
        OaiIdentifierEntity oaiId = (OaiIdentifierEntity) entity;
        StringBuilder result = new StringBuilder();
        result.append("id:").append(oaiId.getId());
        result.append(", base:").append(oaiId.getBase());
        result.append(", sysno:").append(oaiId.getSysno());
        return result.toString();
    }

    private String getIdString(String base, String sysno) {
        StringBuilder result = new StringBuilder();
        result.append("base:").append(base);
        result.append(", sysno:").append(sysno);
        return result.toString();
    }
}
